#include "PieceModel.h"
#include "UpdatePieceNetworkEvent.h"
#include "AddBlockToPieceNetworkEvent.h"
#include <algorithm>

PieceModel::PieceModel(const Position& position)
        : position(position), newPosition(position)
{
}

PieceModel::~PieceModel()
{
    blocks.clear();
}

Positions PieceModel::getBlockPositions()
{
    Positions result;
    for (BlockModels::iterator it = blocks.begin(); it != blocks.end(); ++it)
    {
        result.push_back(newPosition.move((*it)->getPosition()));
    }
    return result;
}

Positions PieceModel::getLocalPositions()
{
    Positions result;
    for (BlockModels::iterator it = blocks.begin(); it != blocks.end(); ++it)
    {
        result.push_back((*it)->getPosition());
    }
    return result;
}

void PieceModel::reset()
{
    newPosition = position;
    for (BlockModels::iterator it = blocks.begin(); it != blocks.end(); ++it)
    {
        (*it)->reset();
    }
}

bool PieceModel::collideWith(PieceModel* other)
{
    if (this == other)
    {
        return false;
    }

    Positions thisPositions = getBlockPositions();
    Positions otherPositions = other->getBlockPositions();
    for (Positions::iterator thisIt = thisPositions.begin(); thisIt != thisPositions.end(); ++thisIt)
    {
        if (std::find(otherPositions.begin(), otherPositions.end(), *thisIt) != otherPositions.end())
        {
            return true;
        }
    }
    return false;
}

void PieceModel::addBlock(const Position& position)
{
    BlockModel* block = new BlockModel(position);
    addChild(block);
    blocks.push_back(block);
    addChangeEvent(new AddBlockToPieceNetworkEvent(getId(), block->getId(), position));
}

void PieceModel::updateClients()
{
    if (position != newPosition)
    {
        position = newPosition;
        addChangeEvent(new UpdatePieceNetworkEvent(getId(), position));
    }
    for (BlockModels::iterator it = blocks.begin(); it != blocks.end(); ++it)
    {
        (*it)->updateClients();
    }
}

void PieceModel::move(const Position& delta)
{
    newPosition = position.move(delta);
}

void PieceModel::rotateCW()
{
    for (BlockModels::iterator it = blocks.begin(); it != blocks.end(); ++it)
    {
        (*it)->rotateCWAround(Position(2, 2));
    }
}

void PieceModel::rotateCCW()
{
    for (BlockModels::iterator it = blocks.begin(); it != blocks.end(); ++it)
    {
        (*it)->rotateCCWAround(Position(2, 2));
    }
}

